﻿using Reader.Chromely.Core;
using Reader.Chromely.Core.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using Xilium.CefGlue;

namespace Reader.Core.Chromely.Core.ProcessMessage
{
    public class ProcessMessageControllerFactory : IDisposable
    {
        private readonly IChromelyContainer _container;

        public ProcessMessageControllerFactory(IChromelyContainer container)
        {
            _container = container;
        }

        public ProcessMessageController CreateControllerInstance(Type type)
        {
            var instance = CreateType(type);
            return instance as ProcessMessageController;
        }
        public IList<string> GetCefV8RegisterMethodName()
        {
            var result = new List<string>();
            var controllers = _container.GetAllInstances(typeof(ProcessMessageController)).ToList();
            if(controllers != null && controllers.Any())
            {
                foreach(var controller in controllers)
                {
                    if(controller != null && controller is ProcessMessageController)
                    {
                        var entity = controller as ProcessMessageController;
                        foreach(var it in entity.GetType().GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public))
                        {
                            result.Add(it.Name);
                        }
                    }
                }
            }
            return result;
        }
        public IDictionary<string,ProcessMessageController> GetCefV8HandlerMethodEntity()
        {
            var result = new Dictionary<string, ProcessMessageController>();
            var controllers = _container.GetAllInstances(typeof(ProcessMessageController)).ToList();
            if(controllers != null && controllers.Any())
            {
                foreach(var controller in controllers)
                {
                    if(controller != null && controller is ProcessMessageController)
                    {
                        var entity = controller as ProcessMessageController;
                        foreach(var it in entity.GetType().GetMethods(BindingFlags.Instance|BindingFlags.DeclaredOnly|BindingFlags.Public))
                        {
                            if (result.Any(s=>s.Key == it.Name))
                            {
                                Logger.Instance.Log.Warn($"{it.Name} method is register");
                            }
                            else
                            {
                                result.Add(it.Name, entity);
                            }
                        }
                    }
                }
            }
            return result;
        }

        private object CreateType(Type type)
        {
            object instance = null;
            foreach (var constructor in type.GetConstructors())
            {
                var parameters = constructor.GetParameters();
                if (parameters.Length == 0)
                {
                    instance = Activator.CreateInstance(type);
                    break;
                }

                var paramValues = new object[parameters.Length];

                for (var ix = 0; ix < parameters.Length; ix++)
                {
                    var parameterInfo = parameters[ix];

                    var iocInstance = _container.GetAllInstances(parameterInfo.ParameterType).FirstOrDefault();
                    var parameterInstance = iocInstance ?? CreateType(parameterInfo.ParameterType);

                    paramValues[ix] = parameterInstance;
                }

                try
                {
                    instance = Activator.CreateInstance(type, paramValues);
                    break;
                }
                catch (Exception ex)
                {
                    Logger.Instance.Log.Error(ex.Message);
                }
            }

            return instance;
        }

        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)。
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。

                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~ProcessMessageControllerFactory()
        // {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器，则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion
    }
}
